package com.lingo.mgr.service.chatSession.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lingo.common.constant.CacheConstants;
import com.lingo.common.core.page.TableDataInfo;

import com.lingo.common.exception.ServiceException;
import com.lingo.common.helper.LoginHelper;
import com.lingo.common.utils.ServletUtils;
import com.lingo.common.utils.StreamUtils;
import com.lingo.common.utils.redis.RedisUtils;
import com.lingo.mgr.domain.ChatSession;
import com.lingo.mgr.domain.ChatSessionRecord;
import com.lingo.mgr.domain.bo.ChatSessionBo;
import com.lingo.mgr.domain.bo.ChatSessionStartBo;
import com.lingo.mgr.domain.vo.ChatSessionMessageVo;
import com.lingo.mgr.domain.vo.ChatSessionStartVo;
import com.lingo.mgr.domain.vo.ChatSessionVo;
import com.lingo.mgr.enums.ChatEunm;
import com.lingo.mgr.enums.ChatGptTokensEunm;
import com.lingo.mgr.enums.ChatMessageStatusEnum;
import com.lingo.mgr.listener.SseEmitterEventSessionListener;
import com.lingo.mgr.mapper.ChatSessionMapper;
import com.lingo.mgr.mapper.ChatSessionRecordMapper;
import com.lingo.mgr.service.OpenAiService;
import com.lingo.mgr.service.chatSession.IChatSessionService;
import com.unfbx.chatgpt.OpenAiClient;
import com.unfbx.chatgpt.OpenAiStreamClient;
import com.unfbx.chatgpt.entity.chat.*;
import com.unfbx.chatgpt.utils.TikTokensUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * 聊天消息会话Service业务层处理
 *
 * @author ruoyi
 * @date 2023-08-30
 */
@RequiredArgsConstructor
@Service
@Slf4j
public class ChatSessionServiceImpl implements IChatSessionService {

    private final ChatSessionMapper baseMapper;

    private final ChatSessionRecordMapper chatSessionRecordMapper;


    private final OpenAiService openAiService;

    private static Integer maxTokens = 4096;



    /**
     * 查询聊天消息会话
     */
    @Override
    public ChatSessionVo queryById(Long id){
        return baseMapper.selectVoById(id);
    }

    /**
     * 查询聊天消息会话列表
     */
    @Override
    public TableDataInfo<ChatSessionStartVo> queryPageList(ChatSessionBo bo) {
        bo.setUserId(LoginHelper.getUserId());
        Page<ChatSessionStartVo> result = baseMapper.selectChatSessionList(bo.build(), bo);
        return TableDataInfo.build(result);
    }


    @Override
    public TableDataInfo<ChatSessionMessageVo> recordBySessionId(ChatSessionBo bo) {
        bo.setUserId(LoginHelper.getUserId());
        Page<ChatSessionMessageVo> result =  chatSessionRecordMapper.selectChatSessionRecordList(bo.build(),bo);
        List<ChatSessionMessageVo> records = result.getRecords();
        List<ChatSessionMessageVo> finallyRecords = new ArrayList<>();
        for (ChatSessionMessageVo record : records) {
            if (StringUtils.isNotBlank(record.getMessageStr())){
                ChatSessionMessageVo messageVo = JSONObject.parseObject(record.getMessageStr(), ChatSessionMessageVo.class);
                if (StringUtils.equals(messageVo.getRole(),Message.Role.ASSISTANT.getName())){
                    messageVo.setUpdateTime(record.getUpdateTime());
                }else {
                    messageVo.setUpdateTime(record.getCreateTime());
                }
                finallyRecords.add(messageVo);
            }
        }
        result.setRecords(finallyRecords);
        result.setTotal(finallyRecords.size());
        return TableDataInfo.build(result);
    }



    /**
     * 查询聊天消息会话列表
     */
    @Override
    public List<ChatSessionVo> queryList(ChatSessionBo bo) {
        LambdaQueryWrapper<ChatSession> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<ChatSession> buildQueryWrapper(ChatSessionBo bo) {
        LambdaQueryWrapper<ChatSession> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getUserId() != null, ChatSession::getUserId, bo.getUserId());
        lqw.eq(bo.getModelId() != null, ChatSession::getModelId, bo.getModelId());
        return lqw;
    }

    /**
     * 新增聊天消息会话
     */
    @Override
    public Boolean insertByBo(ChatSessionBo bo) {
        ChatSession add = BeanUtil.toBean(bo, ChatSession.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setSessionId(add.getSessionId());
        }
        return flag;
    }

    /**
     * 修改聊天消息会话
     */
    @Override
    public Boolean updateByBo(ChatSessionBo bo) {
        ChatSession update = BeanUtil.toBean(bo, ChatSession.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(ChatSession entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除聊天消息会话
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteById(Long id) {
        baseMapper.deleteById(id);
        chatSessionRecordMapper.delete(new LambdaUpdateWrapper<ChatSessionRecord>()
            .eq(ChatSessionRecord::getSessionId,id));
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ChatSessionStartVo start(ChatSessionStartBo bo,HttpServletRequest request) {

//        boolean contains = wordFilter.include(bo.getPrompt());
//        if (contains){
//            throw new ServiceException("根据相关法律法规和政策，不予提问此问题");
//        }
//
//        Boolean flag = sysUserSettingService.checkIsValid();
//        if(!flag){
//            throw new ServiceException("用户VIP已过期");
//        }
//        SysUserSettingVo userSetting = sysUserSettingService.getUserSettingById(LoginHelper.getUserId());
//        Integer todayCount = chatSessionRecordMapper.selectToDayCount(LoginHelper.getUserId());
//        if (todayCount >= userSetting.getOneDayLimit()){
//            throw new ServiceException("今日聊天次数已上限");
//        }
        Long sessionId = bo.getSessionId();
        //1、 如果没有会话id，创建会话id，存数据库
        String prompt = bo.getPrompt();
        if (StringUtils.isBlank(prompt)){
            throw new ServiceException("无会话内容，请发消息对话");
        }
        ChatSession chatSession;
        if (Objects.isNull(sessionId)) {
            String content = prompt.length() <= 20 ? prompt : prompt.substring(0, 19);
            chatSession = ChatSession.builder()
                .modelId(bo.getModelId())
                .userId(LoginHelper.getUserId())
                .sessionName(content)
                .build();
            baseMapper.insert(chatSession);
            sessionId = chatSession.getSessionId();
        } else {
            //2、更新modelId
            chatSession = baseMapper.selectById(sessionId);
            if (Objects.isNull(chatSession)){
                throw new ServiceException("当前聊天会话已被删除，请刷新页面");
            }
            chatSession.setModelId(bo.getModelId());
            baseMapper.updateById(chatSession);
        }

        //3、创建聊天数据
        Message userMessage = Message.builder().role(Message.Role.USER).content(prompt).build();
        userMessage.setContent(prompt);
        ChatSessionRecord sessionRecord = ChatSessionRecord.builder()
            .messageQuestion(JSONObject.toJSONString(userMessage))
            .userId(LoginHelper.getUserId()).sessionId(sessionId)
            .answerResult(ChatMessageStatusEnum.LOADING.getCode())
            .createIp(ServletUtils.getClientIP(request))
            .build();
        chatSessionRecordMapper.insert(sessionRecord);

        //4、统计当前会话指标

        Long count  = chatSessionRecordMapper.selectMessageCountBySessionId(sessionId);

        ChatSessionStartVo startVo = ChatSessionStartVo.builder()
            .sessionName(chatSession.getSessionName())
            .sessionCreateTime(chatSession.getCreateTime())
            .sessionId(chatSession.getSessionId())
            .dataId(sessionRecord.getSessionRecordId())
            .recordCount(count + 1L).build();

        return startVo;
    }



    @Override
    @Transactional(rollbackFor = Exception.class)
    public ChatSessionStartVo reStart(ChatSessionStartBo bo, HttpServletRequest request) {
//        Boolean flag = sysUserSettingService.checkIsValid();
//        if(!flag){
//            throw new ServiceException("用户VIP已过期");
//        }
        Long sessionId = bo.getSessionId();
//        if (Objects.isNull(sessionId)){
//            throw new ServiceException("当前聊天会话已被删除，请刷新页面");
//        }
//        SysUserSettingVo userSetting = sysUserSettingService.queryById(LoginHelper.getUserId());
//        Integer todayCount = chatSessionRecordMapper.selectToDayCount(LoginHelper.getUserId());
//        if (todayCount >= userSetting.getOneDayLimit()){
//            throw new ServiceException("今日聊天次数已上限");
//        }
        ChatSession chatSession = baseMapper.selectById(sessionId);
        ChatSessionRecord chatMessageRecord = chatSessionRecordMapper.selectOne(new LambdaQueryWrapper<ChatSessionRecord>()
            .eq(ChatSessionRecord::getSessionId, sessionId).orderByDesc(ChatSessionRecord::getSessionRecordId).last("limit 1"));
        if (Objects.isNull(chatMessageRecord)){
            throw new ServiceException("当前聊天记录不存在，请重新创建会话");
        }

        chatMessageRecord.setMessageAnswer(null);
        chatSessionRecordMapper.updateById(chatMessageRecord);

        Long count  = chatSessionRecordMapper.selectMessageCountBySessionId(sessionId);

        ChatSessionStartVo startVo = ChatSessionStartVo.builder()
            .sessionName(chatSession.getSessionName())
            .sessionCreateTime(chatSession.getCreateTime())
            .sessionId(chatSession.getSessionId())
            .dataId(chatMessageRecord.getSessionId())
            .recordCount(count + 1L).build();

        return startVo;
    }

    @Override
    public JSONObject getSearchPrompt() {
//        String key = CacheConstants.SEARCH_PROMPT_KEY.concat(String.valueOf(LoginHelper.getUserId()));
//        JSONObject jsonObject = RedisUtils.getCacheObject(key);
//        if (Objects.nonNull(jsonObject)){
//            return jsonObject;
//        }
//        String content = "你是一个AI问答助手，随机生成三条用户可能提问的问题，以JSON格式回复,不要其他解释：\n" +
//            "```json\n" +
//            "  {\n" +
//            "  \"question\":[]\n" +
//            "  }\n" +
//            "```";
//        Message userMessage = Message.builder().role(Message.Role.SYSTEM).content(content).build();
//        OpenAiClient openAiClient = openAiService.getOpenAiClient(1);
//        ChatCompletion chatCompletion = ChatCompletion.builder()
//            .messages(Collections.singletonList(userMessage))
//            .model(ChatCompletion.Model.GPT_3_5_TURBO_16K_0613.getName()).build();
//        try {
//            ChatCompletionResponse chatCompletionResponse = openAiClient.chatCompletion(chatCompletion);
//            List<ChatChoice> choices = chatCompletionResponse.getChoices();
//            log.info("gpt返回的搜索提示词:{}",choices);
//            if (CollUtil.isEmpty(choices)){
//                return null;
//            }
//            Message gptMessage = choices.get(0).getMessage();
//            String gptMessageContent = gptMessage.getContent();
//            jsonObject = JSON.parseObject(gptMessageContent);
//            RedisUtils.setCacheObject(key,jsonObject);
//            RedisUtils.expire(key,60L);
//            return jsonObject;
//        }catch (Exception e){
//            log.error("调用GPT获取搜索提示词报错:",e);
//            return null;
//        }
        return null;
    }


    @Override
    public JSONObject getSimilarPrompt(Long sessionId) {
//        String key = CacheConstants.SIMILAR_PROMPT_KEY
//            .concat(String.valueOf(LoginHelper.getUserId()))
//            .concat(":")
//            .concat(String.valueOf(sessionId));
//        JSONObject jsonObject = RedisUtils.getCacheObject(key);
//        if (Objects.nonNull(jsonObject)){
//            log.info("走缓存查询可能问的问题:{}",jsonObject);
//            return jsonObject;
//        }
//
//        List<ChatSessionRecord> chatMessageRecords = chatSessionRecordMapper.selectList(new LambdaQueryWrapper<ChatSessionRecord>()
//            .eq(ChatSessionRecord::getSessionId, sessionId)
//            .orderByDesc(ChatSessionRecord::getSessionRecordId)
//            .last("limit 3"));
//        Collections.reverse(chatMessageRecords);
//        chatMessageRecords = StreamUtils.sorted(chatMessageRecords, Comparator.comparing(ChatSessionRecord::getSessionRecordId));
//
//        List<Message> messageList = new ArrayList<>();
//        if (CollUtil.isNotEmpty(chatMessageRecords)) {
//            for (ChatSessionRecord chatMessageRecord : chatMessageRecords) {
//                if (StringUtils.isNotBlank(chatMessageRecord.getMessageQuestion())) {
//                    messageList.add(JSONObject.parseObject(chatMessageRecord.getMessageQuestion(), Message.class));
//                }
//                if (StringUtils.isNotBlank(chatMessageRecord.getMessageAnswer())) {
//                    messageList.add(JSONObject.parseObject(chatMessageRecord.getMessageAnswer(), Message.class));
//                }
//            }
//        }
//
////        boolean contains = wordFilter.include(JSONObject.toJSONString(messageList));
////        if (contains){
////            log.info("根据相关法律法规和政策，不予生成此问题");
////            return null;
////        }
//
//        String content = "根据上下文的沟通记录，生成三条用户可能会问的问题，以JSON格式回复,不要其他解释：\n" +
//            "\n" +
//            "  {\n" +
//            "  \"question\":[]\n" +
//            "  }\n" +
//            "";
//        Message userMessage = Message.builder().role(Message.Role.SYSTEM).content(content).build();
//
//        messageList.add(userMessage);
//
//        ChatCompletion.Model model = ChatCompletion.Model.GPT_3_5_TURBO_16K_0613;
//        //3、动态调整tokens长度
//        int tokens = TikTokensUtil.tokens(model.getName(), messageList);
//        ChatGptTokensEunm chatGptTokensEunm = ChatGptTokensEunm.getLengthByName(model.getName());
//        if (Objects.nonNull(chatGptTokensEunm)){
//            maxTokens = chatGptTokensEunm.getLength();
//        }
//        List<Message> shortenedMessages = new ArrayList<>(messageList);
//        while (tokens > maxTokens && !shortenedMessages.isEmpty()) {
//            shortenedMessages.remove(0);
//            tokens = TikTokensUtil.tokens(model.getName(), shortenedMessages);
//        }
//
//
//        log.info("请求获取可能会问的提示词:{}",JSONObject.toJSON(shortenedMessages));
//        OpenAiClient openAiClient = openAiService.getOpenAiClient(1);
//        ChatCompletion chatCompletion = ChatCompletion.builder()
//            .messages(shortenedMessages)
//            .model(model.getName()).build();
//        try {
//            ChatCompletionResponse chatCompletionResponse = openAiClient.chatCompletion(chatCompletion);
//            List<ChatChoice> choices = chatCompletionResponse.getChoices();
//            log.info("gpt返回可能会问的提示词:{}",choices);
//            if (CollUtil.isEmpty(choices)){
//                return null;
//            }
//            Message gptMessage = choices.get(0).getMessage();
//            String gptMessageContent = gptMessage.getContent();
//            jsonObject = JSON.parseObject(gptMessageContent);
//            RedisUtils.setCacheObject(key,jsonObject);
//            RedisUtils.expire(key,60L);
//            return jsonObject;
//        }catch (Exception e){
//            log.info("调用GPT获取搜索提示词报错:",e);
//            return null;
//        }
        return null;
    }

    @NotNull
    private List<Message> getMessagesHistory(Long sessionId) {
        List<ChatSessionRecord> chatMessageRecords = chatSessionRecordMapper.selectList(new LambdaQueryWrapper<ChatSessionRecord>()
            .eq(ChatSessionRecord::getSessionId, sessionId)
            .orderByDesc(ChatSessionRecord::getSessionRecordId)
            .last("limit 5"));
        Collections.reverse(chatMessageRecords);
        List<Message> messageList = new ArrayList<>();
        if (CollUtil.isNotEmpty(chatMessageRecords)) {
            for (ChatSessionRecord chatMessageRecord : chatMessageRecords) {
                if (StringUtils.isNotBlank(chatMessageRecord.getMessageQuestion())) {
                    messageList.add(JSONObject.parseObject(chatMessageRecord.getMessageQuestion(), Message.class));
                }
                if (StringUtils.isNotBlank(chatMessageRecord.getMessageAnswer())) {
                    messageList.add(JSONObject.parseObject(chatMessageRecord.getMessageAnswer(), Message.class));
                }
            }
        }
        return messageList;
    }


    @Override
    public SseEmitter sse(Long sessionId, Long dataId) {
//        Boolean flag = sysUserSettingService.checkIsValid();
//        if(!flag){
//            throw new ServiceException("用户VIP已过期");
//        }


        //1、 获取历史数据
        List<Message> messageList = getMessagesHistory(sessionId);

        if (CollectionUtils.isEmpty(messageList)) {
            throw new ServiceException("请求参数查询为空");
        }
        ChatSession chatSession = baseMapper.selectById(sessionId);
        if (Objects.isNull(chatSession)){
            throw new ServiceException("当前聊天会话已被删除，请刷新页面");
        }

        //2、聊天


        //3、动态调整tokens长度
//        int tokens = TikTokensUtil.tokens(model.getName(), messageList);
//        ChatGptTokensEunm chatGptTokensEunm = ChatGptTokensEunm.getLengthByName(model.getName());
//        if (Objects.nonNull(chatGptTokensEunm)){
//            maxTokens = chatGptTokensEunm.getLength();
//        }
//        List<Message> shortenedMessages = new ArrayList<>(messageList);
//        while (tokens > maxTokens && !shortenedMessages.isEmpty()) {
//            shortenedMessages.remove(0);
//            tokens = TikTokensUtil.tokens(model.getName(), shortenedMessages);
//        }


        //4、超时时间设为1小时
        SseEmitter sseEmitter = new SseEmitter(3600000L);
        SseEmitterEventSessionListener sessionListener = new SseEmitterEventSessionListener(sseEmitter, dataId, chatSessionRecordMapper);

        OpenAiStreamClient openAiStreamClient = openAiService.getOpenAiStreamClient(1);

        ChatCompletion chatCompletion = ChatCompletion.builder()
            .messages(messageList)
            .model(BaseChatCompletion.Model.GPT_3_5_TURBO_16K_0613.getName())
            .build();
        openAiStreamClient.streamChatCompletion(chatCompletion, sessionListener);
        sseEmitter.onCompletion(() -> {
            log.info("SseEmitter 请求 dateId:[{}] 执行结束!", dataId);
        });

        sseEmitter.onError(throwable -> {
            log.info("SseEmitter执行失败, dateId:[" + dataId + "]", throwable);
        });
        return sseEmitter;
    }


}
